import {InvokeCodeService} from './invoke-code-service';
import {InvokeUtils} from '../../utils/invoke-utils';
import {InvokeDataRest} from '../../entity/invoke-data-rest';

export class CurlInvokeCodeService implements InvokeCodeService {
    getCode(data: InvokeDataRest): string {
        const code = [];
        code.push('``` bash \n');
        code.push('curl -X ');
        code.push(data.method.toUpperCase());
        code.push(' \'');

        code.push(InvokeUtils.getUrl(data));

        code.push('\' \\\n');

        const headerKeys = new Set();
        if (data.headers) {
            data.headers.forEach(header => {
                if (header.key.length === 0) {
                    return;
                }
                if (headerKeys.has(header.key)) {
                    return;
                }
                headerKeys.add(header.key);
                this.addHeader(code, header);
            });
        }
        if (data.env.headers) {
            data.env.headers.forEach(header => {
                if (header.key.length === 0 || headerKeys.has(header.key)) {
                    return;
                }
                headerKeys.add(header.key);
                this.addHeader(code, header);
            });
        }

        if (data.method === 'POST' && data.requestBody) {
            if (data.requestBody.rawDataType === 'raw' && data.requestBody.rawData) {
                this.renderRawCommend(code, data);
            } else {
                if (data.requestBody.rawDataType === 'x-www-form-urlencoded') {
                    this.renderFormUrlEncodedCommend(code, data);
                } else if (data.requestBody.rawDataType === 'form-data') {
                    this.renderFormDataCommend(code, data);
                }
            }
        }

        code.splice(code.length - 1, 1);
        code.push('\n```');
        return code.join('');
    }

    private addHeader(code: string[], header) {
        code.push('\t -H \'');
        code.push(header.key);
        code.push(': ');
        code.push(header.value);
        code.push('\'');
        code.push(' \\\n');
    }

    private renderFormDataCommend(code: string[], data: InvokeDataRest) {
        data.requestBody.formData.forEach(item => {
            if (!item.key) {
                return;
            }
            code.push(`\t -F ${item.key}=${item.value}`);
            code.push(' \\\n');
        });
    }

    private renderFormUrlEncodedCommend(code: string[], data: InvokeDataRest) {
        const urlParams = InvokeUtils.joinUrlEncodedParams(data.requestBody.formData);
        if (urlParams) {
            code.push('\t -F ');
            code.push(urlParams);
            code.push(' \\\n');
        }
    }

    private renderRawCommend(code: string[], data: InvokeDataRest) {
        code.push('\t -d \'');
        code.push(data.requestBody.rawData);
        code.push('\'');
        code.push(' \\\n');
    }
}
